package rede.treinamento;
import static jogo.SimboloJogada.O;
import static jogo.SimboloJogada.X;
import static jogo.SimboloJogada._;
import static org.junit.Assert.assertEquals;
import jogo.SimboloJogada;
import jogo.Tabuleiro;

import org.junit.Before;
import org.junit.Test;


public class CalculadorScoreTest {

	private static final double ERRO = 0.001;
	private Tabuleiro tabuleiroVazio, tabuleiroInicial, tabuleiro01, tabuleiro02, tabuleiro03;
	private SimboloJogada[][] vazio = { { _, _, _ }, { _, _, _ }, { _, _, _ } };

	private SimboloJogada[][] inicial = { { _, _, _ }, { _, X, _ }, { _, _, _ } };

	private SimboloJogada[][] config01 = { 
			{ O, _, _ }, 
			{ _, X, _ }, 
			{ X, _, _ } };
	
	private SimboloJogada[][] config02 = { 
			{ O, _, _ }, 
			{ _, X, _ }, 
			{ X, _, O } };

	private SimboloJogada[][] config03 = { 
			{ O, O, _ }, 
			{ _, _, _ }, 
			{ X, X, _ } };


	@Before
	public void setUp() {
		tabuleiroVazio = makeTabuleiro(vazio);
		tabuleiroInicial = makeTabuleiro(inicial);
		tabuleiro01 = makeTabuleiro(config01);
		tabuleiro02 = makeTabuleiro(config02);
		tabuleiro03 = makeTabuleiro(config03);
	}

	@Test
	public void testCalculaScoresTabuleiroVazio() {
		double esperado = 1.0 / 9;

		Double[][] scores = CalculadorScore.calculaScores(tabuleiroVazio, X);
		for (int i = 0; i < scores.length; i++) {
			for (int j = 0; j < scores[i].length; j++) {
				assertEquals(esperado, scores[i][j], ERRO);
			}
		}
	}

	@Test
	public void testCalculaScoresTabuleiroInicial() {
		double normal = 1.0 / 8;
		Double[][] esperados = { { normal, normal, normal }, { normal, Double.NaN, normal },
				{ normal, normal, normal } };

		Double[][] scores = CalculadorScore.calculaScores(tabuleiroInicial, O);
		for (int i = 0; i < scores.length; i++) {
			for (int j = 0; j < scores[i].length; j++) {
				assertEquals(esperados[i][j], scores[i][j]);
			}
		}

		scores = CalculadorScore.calculaScores(tabuleiroInicial, X);
		for (int i = 0; i < scores.length; i++) {
			for (int j = 0; j < scores[i].length; j++) {
				assertEquals(esperados[i][j], scores[i][j]);
			}
		}
	}

	@Test
	public void testCalculaScoresTabuleiro01() {
		double normal = 1.0 / 5;
		Double[][] esperados = {{Double.NaN, normal, CalculadorScore.SCORE_DEFESA},{normal, Double.NaN, normal},{Double.NaN, normal, normal}};

		Double[][] scores = CalculadorScore.calculaScores(tabuleiro01, O);
		for (int i = 0; i < scores.length; i++) {
			for (int j = 0; j < scores[i].length; j++) {
				assertEquals(esperados[i][j], scores[i][j]);
			}
		}
	}

	@Test
	public void testCalculaScoresTabuleiro02() {
		double normal = 1.0 / 4;
		Double[][] esperados = {{Double.NaN, normal, CalculadorScore.SCORE_DEFESA},{normal, Double.NaN, normal},{Double.NaN, normal, Double.NaN}};

		Double[][] scores = CalculadorScore.calculaScores(tabuleiro02, O);
		for (int i = 0; i < scores.length; i++) {
			for (int j = 0; j < scores[i].length; j++) {
				assertEquals(esperados[i][j], scores[i][j]);
			}
		}
		
		normal = 1.0 / 4;
		esperados = new Double[][]{{Double.NaN, normal, CalculadorScore.SCORE_MATCHPOINT},{normal, Double.NaN, normal},{Double.NaN, normal, Double.NaN}};
		scores = CalculadorScore.calculaScores(tabuleiro02, X);
		for (int i = 0; i < scores.length; i++) {
			for (int j = 0; j < scores[i].length; j++) {
				assertEquals(esperados[i][j], scores[i][j]);
			}
		}
	}
	
	@Test
	public void testCalculaScoresTabuleiro03() {
		double normal = 1.0 / 3;
		Double[][] esperados = {{Double.NaN, Double.NaN, CalculadorScore.SCORE_MATCHPOINT},{normal, normal, normal},{Double.NaN, Double.NaN, CalculadorScore.SCORE_DEFESA}};

		Double[][] scores = CalculadorScore.calculaScores(tabuleiro03, O);
		for (int i = 0; i < scores.length; i++) {
			for (int j = 0; j < scores[i].length; j++) {
				assertEquals(esperados[i][j], scores[i][j]);
			}
		}
		
		normal = 1.0 / 3;
		esperados = new Double[][]{{Double.NaN, Double.NaN, CalculadorScore.SCORE_DEFESA},{normal, normal, normal},{Double.NaN, Double.NaN, CalculadorScore.SCORE_MATCHPOINT}};
		scores = CalculadorScore.calculaScores(tabuleiro03, X);
		for (int i = 0; i < scores.length; i++) {
			for (int j = 0; j < scores[i].length; j++) {
				assertEquals(esperados[i][j], scores[i][j]);
			}
		}
	}

	private Tabuleiro makeTabuleiro(SimboloJogada[][] simbolos) {
		Tabuleiro tab = new Tabuleiro();
		for (int i = 0; i < simbolos.length; i++) {
			for (int j = 0; j < simbolos[i].length; j++) {
				tab.setSimbolo(i, j, simbolos[i][j]);
			}
		}
		return tab;
	}

}
